from starlette.endpoints import HTTPEndpoint
from starlette.responses import JSONResponse
from database import Session
import logging
from dao import DaoSuperviseRecord
from model.ModSuperviseRecord import SuperviseRecord, superviseRecordSchema
from model.ModPhotoIndex import PhotoIndex
import config
import requests
import tempfile
from typing import Optional, Tuple
import imagehash
from redis_connection import redis_conn as redis
from utils import Switch
from PIL import Image
import pendulum
import os
import os.path
from uuid import UUID
# 供电所督办反馈页面
class SuperviseConfirmStation(HTTPEndpoint):

    async def get(self, request):
        session = Session()
        try:
            bureauid = request.query_params["bureauid"]
            stationid = request.query_params["stationid"]
            return  DaoSuperviseRecord.get_supervise_station_list(session, bureauid, stationid)
        finally:
            session.close()

# 供电所督办反馈页面详细信息
class SuperviseConfirmStationDetail(HTTPEndpoint):
    def __init__(self, scope):
        super().__init__(scope)
        self._logger = logging.getLogger(type(self).__name__)
    async def get(self, request):
        session = Session()
        try:
            bureauid = request.query_params["bureauid"]
            meter_barcode = request.query_params["meter_barcode"]
            serial_number = request.query_params["serial_number"]
            return  DaoSuperviseRecord.get_supervise_station_detail(session, bureauid, meter_barcode, serial_number)
        finally:
            session.close()

    async def post(self, request):
        session = Session()
        try:
            dict_rec = await request.json()
            photo_fingerprint = ""
            if len(dict_rec["photo_fingerprint"]) > 0:
                photo = self._save_picture(dict_rec["photo_fingerprint"])
                if photo is None:
                   raise OSError()
                photo_fingerprint, photo_path = photo
                self._logger.debug(f"Photo: {photo_fingerprint}")
                new_photo = PhotoIndex(photo_fingerprint=photo_fingerprint,
                                       storage_path=config.UPLOAD_PATH,
                                      access_path=photo_path)
                session.add(new_photo)
            record = SuperviseRecord()
            record.serial_number = UUID(dict_rec.get("serial_number"))
            record.bureauid = dict_rec.get("bureauid")
            record.meter_barcode = dict_rec.get("meter_barcode")
            record.flag_result = dict_rec.get("flag_result")
            record.stationid = dict_rec.get("stationid")
            record.openid_station = dict_rec.get("openid_station")
            record.time_station = pendulum.now("Asia/Shanghai")
            record.remark_station = dict_rec.get("remark_station")
            record.bureauname = dict_rec.get("bureauname")
            record.stationname = dict_rec.get("stationname")
            record.name_station = dict_rec.get("name_station")
            record.photo_fingerprint = photo_fingerprint
            record.time_problem = dict_rec.get("time_problem")
            record.problemid = dict_rec.get("problemid")
            record.proname = dict_rec.get("proname")
            DaoSuperviseRecord.insert_supervise_record(session, record)
            session.commit()
        except Exception:
            session.rollback()
            return JSONResponse({"result": "0"})
        else:
            return JSONResponse({"result": "1"})
        finally:
            session.close()

    def _save_picture(self, media_id: str) -> Optional[Tuple[str, str]]:
        """
        用微信素材的Media ID来下载指定素材图片，并计算图片指纹。
        注意：本下载方法仅支持JPEG和PNG两种文件格式，由微信返回的响应头属性Content-Type确定。
        :param media_id: 素材Media ID
        :return: 返回元组(图片指纹，图片保存路径)，如果出现下载错误等，则返回None。
        """
        try:
            token = redis.hget(config.PUB_ACCESS_TOKEN, "token")
            media_file_request = requests.get(f"https://api.weixin.qq.com/cgi-bin/media/get",
                                              params={
                                                  "access_token": token,
                                                  "media_id": media_id
                                              },
                                              stream=True)
            media_file_request.raise_for_status()

            # 判断上传的文件类型
            content_type = media_file_request.headers["Content-Type"]
            file_type = ""
            for case in Switch(content_type.lower()):
                if case("image/jpeg"):
                    file_type = "jpg"
                    break
                if case("image/png"):
                    file_type = "png"
                    break
                if case():
                    self._logger.debug(f"响应头中的Content-Type为{content_type.lower()}")
                    raise ValueError("Unsupported content type")
            # 转置到临时文件计算图片指纹，之后再转置到uploads目录
            with tempfile.TemporaryFile() as tmp:
                for chunk in media_file_request.iter_content(chunk_size=512):
                    if chunk:
                        tmp.write(chunk)
                image_fingerprint = imagehash.phash(Image.open(tmp))
                image_file_name = f"{image_fingerprint}.{file_type}"
                upload_file_name = f"{config.UPLOAD_PATH}/{image_file_name}"
                if not os.path.exists(f"{config.UPLOAD_PATH}"):
                    os.makedirs(f"{config.UPLOAD_PATH}")
                with open(upload_file_name, "wb") as upload:
                    tmp.seek(0)
                    while True:
                        content = tmp.read(512)
                        if not content:
                            break
                        upload.write(content)

            return str(image_fingerprint), image_file_name
        except OSError:
            self._logger.info("文件转置失败，将目录设为了移动目标。")
            return None
        except ValueError:
            self._logger.info("微信素材解析失败，因为Content-Type无法识别。")
            return None
        except requests.HTTPError:
            self._logger.info("微信素材下载请求失败。")
            return None

class SuperviseConfirmStationCount(HTTPEndpoint):
    async def get(self, request):
        session = Session()
        try:
            bureauid = request.query_params["bureauid"]
            stationid = request.query_params["stationid"]
            cou = DaoSuperviseRecord.get_supervise_confirm_station_count(session, bureauid, stationid)
            return JSONResponse({"result": cou})
        finally:
            session.close()